#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

template<typename T, typename ...ARGS>
class BASE {
public:
    virtual T run(ARGS...) = 0;
    virtual BASE<T, ARGS...> *getCopy() = 0;
    virtual ~BASE() {}
};

template<typename T, typename ...ARGS>
class normal_function : public BASE<T, ARGS...>{
public:
    normal_function(T (*func)(ARGS...)) : func(func) {}
    T run(ARGS ...args) override {
        return func(forward<ARGS>(args)...);
    }
    BASE<T, ARGS...> *getCopy() override {
        return new normal_function<T, ARGS...>(*this);
    }
private:
    T (*func)(ARGS...);
};

template<typename CLASS_T, typename T, typename ...ARGS>
class functor : public BASE<T, ARGS...> {
public:
    functor(CLASS_T obj) : obj(obj) {}
    T run(ARGS...args) override {
        return obj(forward<ARGS>(args)...);
    }
    BASE<T, ARGS...> *getCopy() override {
        return new functor<CLASS_T, T, ARGS...>(*this);
    }
private:
    CLASS_T obj;
};

template<typename T, typename ...ARGS> class function {};
template<typename T, typename ...ARGS>
class function<T(ARGS...)> {
public:
    function(T (*ptr)(ARGS...)) : ptr(new normal_function<T, ARGS...>(ptr)) {}
    template<typename CLASS_T>
    function(CLASS_T obj) : ptr(new functor<CLASS_T, T, ARGS...>(obj)) {}
    T operator()(ARGS ...args) {
        return ptr->run(forward<ARGS>(args)...);
    }
    ~function() {

    }
private:
    BASE<T, ARGS...> *ptr;
};

int add(int a, int b) {
    cout << "normal function : ";
    return a + b;
}

class ADD_MULT {
public :
    ADD_MULT(int x) : x(x) {}
    int operator()(int a, int b) {
        cout << "functor : ";
        return (a + b) * 2;
    }
private:
    int x;
};

int main() {
    ADD_MULT add_mult(2);
    function<int(int, int)> f1 = add;
    function<int(int, int)> f2 = add_mult;
    cout << f1(3, 4) << endl;
    cout << f2(3, 4) << endl;
    f1 = f2;
    cout << f1(3, 4) << endl;

    return 0;
}

ENDS(test1)

int main() {
    test1::main();
    return 0;
}